home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / XPR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  53.3 KB  |  2,609 lines

  1. /*
  2. **    XPR.c
  3. **
  4. **    External transfer protocol support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* These variables keep the transferred bytes and transfer
  17.      * time in seconds.
  18.      */
  19.  
  20. STATIC LONG             ByteVal,
  21.                      ByteMax,
  22.                      TimeVal,
  23.                      TimeMax,
  24.  
  25.                      LastTimeDif,
  26.                      LastPercent;
  27.  
  28.     /* Transfer statistics. */
  29.  
  30. STATIC ULONG         CPS_Minimum,
  31.                      CPS_Maximum,
  32.                      CPS_Average,
  33.                      CPS_Current,
  34.                      CPS_Count,
  35.                      CPS_Last;
  36.  
  37.     /* The name of the file being transmitted, in case the
  38.      * `override transfer path' feature is enabled.
  39.      */
  40.  
  41. STATIC struct Buffer    *CurrentFile;
  42.  
  43.     /* Yet another flag, this one determines whether we already told
  44.      * the user that the file we are currently processing will fit
  45.      * on the destination device.
  46.      */
  47.  
  48. STATIC BOOL             Alerted,
  49.                      DontWorry,
  50.                      TypeChecked,
  51.                      ErrorNotified,
  52.                      CarrierMessage;
  53.  
  54. STATIC UBYTE __far     RealName[MAX_FILENAME_LENGTH];
  55. STATIC ULONG         LastSeconds;
  56.  
  57.     /* PrintBox(LONG Box,LONG Line,STRPTR String,...):
  58.      *
  59.      *    Update the contents of a text box.
  60.      */
  61.  
  62. STATIC VOID __stdargs
  63. PrintBox(LONG Box,LONG Line,STRPTR String,...)
  64. {
  65.     UBYTE     LocalBuffer[256];
  66.     va_list     VarArgs;
  67.  
  68.     va_start(VarArgs,String);
  69.     VSPrintf(LocalBuffer,String,VarArgs);
  70.     va_end(VarArgs);
  71.  
  72.     LT_SetAttributes(TransferHandle,Box,
  73.         LABX_Index,    Line,
  74.         LABX_Text,    LocalBuffer,
  75.     TAG_DONE);
  76. }
  77.  
  78.     /* OpenTransferWindow():
  79.      *
  80.      *    Local routine to open the transfer window.
  81.      */
  82.  
  83. STATIC BOOL
  84. OpenTransferWindow(VOID)
  85. {
  86.         /* Block window input. */
  87.  
  88.     BlockWindows();
  89.  
  90.         /* Try to open the transfer window panel. */
  91.  
  92.     if(TransferPanel(LocaleString(MSG_TERMXPR_RECEIVE_FILES_TXT)))
  93.     {
  94.             /* Supply the log text. */
  95.  
  96.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_INITIATE_BINARY_DOWNLOAD_TXT));
  97.  
  98.             /* Return success. */
  99.  
  100.         return(TRUE);
  101.     }
  102.     else
  103.     {
  104.             /* Re-enable window input. */
  105.  
  106.         ReleaseWindows();
  107.  
  108.             /* Return failure. */
  109.  
  110.         return(FALSE);
  111.     }
  112. }
  113.  
  114.     /* CheckAbort(BOOLEAN CheckCarrier):
  115.      *
  116.      *    Check for transfer abort.
  117.      */
  118.  
  119. STATIC LONG
  120. CheckAbort(BOOLEAN CheckCarrier)
  121. {
  122.     struct IntuiMessage    *Message;
  123.     ULONG                 MsgClass,
  124.                          MsgQualifier;
  125.     UWORD                 MsgCode;
  126.     struct Gadget        *MsgGadget;
  127.     struct Window        *MsgWindow;
  128.     LONG                 Result = 0;
  129.  
  130.         /* No window available for output? */
  131.  
  132.     if(!TransferWindow)
  133.     {
  134.         if(!OpenTransferWindow())
  135.             return(-1);
  136.     }
  137.  
  138.         /* Are we to check the carrier status? */
  139.  
  140.     if(CheckCarrier)
  141.     {
  142.             /* Return error if carrier is lost. */
  143.  
  144.         if(GetSerialStatus() & CIAF_COMCD)
  145.         {
  146.             if(!CarrierMessage)
  147.             {
  148.                 CarrierMessage = TRUE;
  149.  
  150.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  151.             }
  152.  
  153.             SetOnlineState(FALSE);
  154.  
  155.             TransferError = TRUE;
  156.  
  157.             return(-1);
  158.         }
  159.     }
  160.  
  161.         /* Process all incoming messages. */
  162.  
  163.     while(Message = (struct IntuiMessage *)GT_GetIMsg(TransferWindow->UserPort))
  164.     {
  165.         MsgClass        = Message->Class;
  166.         MsgQualifier    = Message->Qualifier;
  167.         MsgCode            = Message->Code;
  168.         MsgGadget        = (struct Gadget *)Message->IAddress;
  169.         MsgWindow        = Message->IDCMPWindow;
  170.  
  171.         GT_ReplyIMsg(Message);
  172.  
  173.         if(MsgWindow == TransferWindow)
  174.         {
  175.             if(!Result)
  176.             {
  177.                 LT_HandleInput(TransferHandle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  178.  
  179.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  180.                 {
  181.                     LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  182.  
  183.                     TransferAborted = TRUE;
  184.  
  185.                     Result = -1;
  186.                 }
  187.  
  188.                 if(MsgClass == IDCMP_GADGETUP)
  189.                 {
  190.                     switch(MsgGadget->GadgetID)
  191.                     {
  192.                         case GAD_TRANSFER_ABORT:
  193.  
  194.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  195.  
  196.                             TransferAborted = TRUE;
  197.  
  198.                             Result = -1;
  199.  
  200.                             break;
  201.  
  202.                         case GAD_TRANSFER_SKIP:
  203.  
  204.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_SKIPPED_TXT));
  205.  
  206.                             Result = 1;
  207.  
  208.                             break;
  209.  
  210.                         case GAD_TRANSFER_ABORT_FILE:
  211.  
  212.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_ABORTED_TXT));
  213.  
  214.                             Result = 2;
  215.  
  216.                             break;
  217.                     }
  218.                 }
  219.             }
  220.         }
  221.     }
  222.  
  223.     return(Result);
  224. }
  225.  
  226.     /* NewFileName(STRPTR Source,STRPTR Buffer):
  227.      *
  228.      *    Build a valid file and path name, including path
  229.      *    substitution, etc.
  230.      */
  231.  
  232. STATIC STRPTR
  233. NewFileName(STRPTR Source,STRPTR Buffer)
  234. {
  235.     if(Config->TransferConfig->OverridePath && !Uploading)
  236.     {
  237.         if(DownloadPath)
  238.             strcpy(Buffer,DownloadPath);
  239.         else
  240.             strcpy(Buffer,Config->PathConfig->BinaryDownloadPath);
  241.  
  242.         if(!Buffer[0])
  243.         {
  244.             if(!GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  245.                 Buffer[0] = 0;
  246.         }
  247.  
  248.         if(Buffer[0])
  249.         {
  250.             if(AddPart(Buffer,FilePart(Source),MAX_FILENAME_LENGTH))
  251.                 return(Buffer);
  252.         }
  253.     }
  254.     else
  255.     {
  256.         if(FilePart(Source) == Source)
  257.         {
  258.             if(GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  259.             {
  260.                 if(AddPart(Buffer,Source,MAX_FILENAME_LENGTH))
  261.                     return(Buffer);
  262.             }
  263.         }
  264.     }
  265.  
  266.     strcpy(Buffer,Source);
  267.  
  268.     return(Source);
  269. }
  270.  
  271.     /* IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate):
  272.      *
  273.      *    Attach source information (BBS name, date and time) to a file.
  274.      */
  275.  
  276. STATIC VOID
  277. IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate)
  278. {
  279.     UBYTE            LocalBuffer[MAX_FILENAME_LENGTH],
  280.                     Time[40],
  281.                     Date[40];
  282.     struct DateTime    DateTime;
  283.  
  284.     CopyMem(OpenDate,&DateTime.dat_Stamp,sizeof(struct DateStamp));
  285.  
  286.         /* Prepare for date conversion. */
  287.  
  288.     DateTime.dat_Format    = FORMAT_DOS;
  289.     DateTime.dat_Flags    = 0;
  290.     DateTime.dat_StrDay    = NULL;
  291.     DateTime.dat_StrDate    = Date;
  292.     DateTime.dat_StrTime    = Time;
  293.  
  294.         /* Convert the date. */
  295.  
  296.     if(DateToStr(&DateTime))
  297.     {
  298.         StripSpaces(BBSName);
  299.         StripSpaces(Date);
  300.         StripSpaces(Time);
  301.  
  302.         if(BBSName[0])
  303.             SPrintf(LocalBuffer,"%s %s %s",BBSName,Date,Time);
  304.         else
  305.             SPrintf(LocalBuffer,"%s %s",Date,Time);
  306.  
  307.         SetComment(Name,LocalBuffer);
  308.     }
  309. }
  310.  
  311.     /* GetSeconds(STRPTR String):
  312.      *
  313.      *    Tries to turn a string of the format hh:mm:ss into
  314.      *    an integer number.
  315.      */
  316.  
  317. STATIC LONG
  318. GetSeconds(STRPTR String)
  319. {
  320.     UBYTE    Buffer[20];
  321.     LONG    Seconds = 0;
  322.  
  323.     memset(Buffer,0,20);
  324.  
  325.     strcpy(Buffer,String);
  326.  
  327.     Seconds += Atol(&Buffer[6]);
  328.  
  329.     Buffer[5] = 0;
  330.  
  331.     Seconds += Atol(&Buffer[3]) * 60;
  332.  
  333.     Buffer[2] = 0;
  334.  
  335.     Seconds += Atol(&Buffer[0]) * 3600;
  336.  
  337.     return(Seconds);
  338. }
  339.  
  340.     /* TruncateName(STRPTR FileName):
  341.      *
  342.      *    Truncates a file name to a maximum of 48 characters.
  343.      */
  344.  
  345. STATIC STRPTR
  346. TruncateName(STRPTR FileName)
  347. {
  348.     LONG Len = strlen(FileName);
  349.  
  350.     if(Len > 48)
  351.     {
  352.         LONG i;
  353.  
  354.         for(i = Len - 48 ; i < Len ; i++)
  355.         {
  356.             if(i >= Len - 44 && FileName[i] == '/')
  357.             {
  358.                 STATIC UBYTE __far NameBuffer[MAX_FILENAME_LENGTH];
  359.  
  360.                 strcpy(NameBuffer,".../");
  361.  
  362.                 strcat(NameBuffer,&FileName[i + 1]);
  363.  
  364.                 return(NameBuffer);
  365.             }
  366.         }
  367.     }
  368.  
  369.     return(FileName);
  370. }
  371.  
  372.     /* IsBlockMappedDevice(struct MsgPort *Handler):
  373.      *
  374.      *    See if the lock given points to a block mapped filing
  375.      *    system.
  376.      */
  377.  
  378. STATIC BOOL
  379. IsBlockMappedDevice(struct MsgPort *Handler)
  380. {
  381.     struct DosList    *Entry;
  382.     BOOL             IsBlockMapped = FALSE;
  383.  
  384.         // Find the device the lock belongs to
  385.  
  386.     if(Entry = LockDosList(LDF_DEVICES | LDF_READ))
  387.     {
  388.         while(Entry = NextDosEntry(Entry,LDF_DEVICES))
  389.         {
  390.             if(Entry->dol_Task == Handler)
  391.             {
  392.                 struct FileSysStartupMsg *Startup = (struct FileSysStartupMsg *)BADDR(Entry->dol_misc.dol_handler.dol_Startup);
  393.  
  394.                     // Plain filing system usually don't
  395.                     // use the startup entry
  396.  
  397.                 if(TypeOfMem(Startup))
  398.                 {
  399.                     STRPTR             Name        = (STRPTR)BADDR(Startup->fssm_Device);
  400.                     struct DosEnvec    *Environ    = (struct DosEnvec *)BADDR(Startup->fssm_Environ);
  401.  
  402.                         // Valid data in the startup entry?
  403.  
  404.                     if(TypeOfMem(Name) && TypeOfMem(Environ))
  405.                     {
  406.                         struct IOStdReq __aligned Request;
  407.  
  408.                         memset(&Request,0,sizeof(struct IOStdReq));
  409.  
  410.                             // Last chance, try to open the device driver
  411.  
  412.                         if(!OpenDevice(Name + 1,Startup->fssm_Unit,&Request,Startup->fssm_Flags))
  413.                         {
  414.                                 // This is a block mapped filing system
  415.  
  416.                             IsBlockMapped = TRUE;
  417.  
  418.                             CloseDevice(&Request);
  419.  
  420.                             break;
  421.                         }
  422.                     }
  423.                 }
  424.             }
  425.         }
  426.  
  427.         UnLockDosList(LDF_DEVICES | LDF_READ);
  428.     }
  429.  
  430.     return(IsBlockMapped);
  431. }
  432.  
  433.     /* CalculateBlocks(LONG Size,LONG BlockSize):
  434.      *
  435.      *    Calculate the number of blocks a file will
  436.      *    occupy if saved to a disk.
  437.      */
  438.  
  439. STATIC LONG
  440. CalculateBlocks(LONG Size,LONG BlockSize)
  441. {
  442.     LONG    Blocks            = 1;        /* One for the file header. */
  443.     LONG    Extension        = 0;        /* How many block pointers yet. */
  444.     BOOL    HasExtension    = FALSE;    /* No extension block yet. */
  445.  
  446.         /* Round to next block. */
  447.  
  448.     Size = ((Size + BlockSize - 1) / BlockSize) * BlockSize;
  449.  
  450.     while(Size)
  451.     {
  452.             /* Add another block. */
  453.  
  454.         Blocks++;
  455.  
  456.             /* Subtract another block. */
  457.  
  458.         Size -= BlockSize;
  459.  
  460.             /* Add another block pointer, if 72 have been
  461.              * added, add another extension block.
  462.              */
  463.  
  464.         if((Extension++) == 72)
  465.         {
  466.                 /* If no extension block has been generated
  467.                  * yet, we were running on the block pointers
  468.                  * of the file header itself.
  469.                  */
  470.  
  471.             if(!HasExtension)
  472.                 HasExtension = TRUE;
  473.             else
  474.                 Blocks++;
  475.  
  476.                 /* Reset extension block counter. */
  477.  
  478.             Extension = 0;
  479.         }
  480.     }
  481.  
  482.     return(Blocks);
  483. }
  484.  
  485.     /* SerialErrorReport(struct IOExtSer *Request):
  486.      *
  487.      *    Report a certain I/O error cause.
  488.      */
  489.  
  490. STATIC BYTE
  491. SerialErrorReport(struct IOExtSer *Request)
  492. {
  493.     STRPTR    ErrorMessage;
  494.     BOOL    IsFatal;
  495.  
  496.     switch(Request->IOSer.io_Error)
  497.     {
  498.         case SerErr_LineErr:
  499.  
  500.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_HARDWARE_DATA_OVERRUN_TXT);
  501.  
  502.             IsFatal = FALSE;
  503.  
  504.             break;
  505.  
  506.         case SerErr_ParityErr:
  507.  
  508.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_PARITY_ERROR_TXT);
  509.  
  510.             IsFatal = TRUE;
  511.  
  512.             break;
  513.  
  514.         case SerErr_TimerErr:
  515.  
  516.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_TIMER_ERROR_TXT);
  517.  
  518.             IsFatal = FALSE;
  519.  
  520.             break;
  521.  
  522.         case SerErr_BufOverflow:
  523.  
  524.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_READ_BUFFER_OVERFLOWED_TXT);
  525.  
  526.             IsFatal = FALSE;
  527.  
  528.             break;
  529.  
  530.         case SerErr_NoDSR:
  531.  
  532.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_NO_DSR_TXT);
  533.  
  534.             IsFatal = TRUE;
  535.  
  536.             break;
  537.  
  538.         case SerErr_DetectedBreak:
  539.  
  540.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_BREAK_DETECTED_TXT);
  541.  
  542.             IsFatal = TRUE;
  543.  
  544.             break;
  545.  
  546.         default:
  547.  
  548.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_UNKNOWN_CAUSE_TXT);
  549.  
  550.             IsFatal = FALSE;
  551.  
  552.             break;
  553.     }
  554.  
  555.     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_ERROR_TEMPLATE_TXT),Request->IOSer.io_Error,ErrorMessage);
  556.  
  557.     if(IsFatal)
  558.     {
  559.         TransferError = TRUE;
  560.  
  561.         return(TRUE);
  562.     }
  563.     else
  564.         return(FALSE);
  565. }
  566.  
  567.     /* xpr_fopen(STRPTR FileName,STRPTR AccessMode):
  568.      *
  569.      *    Open a file for random access.
  570.      */
  571.  
  572. LONG __saveds __asm
  573. xpr_fopen(REG(a0) STRPTR FileName,REG(a1) STRPTR AccessMode)
  574. {
  575.     UBYTE             RealName[MAX_FILENAME_LENGTH];
  576.     struct Buffer    *File;
  577.  
  578.     DB(kprintf("xpr_fopen(\"%s\",\"%s\")\n",FileName,AccessMode));
  579.  
  580.     Alerted = CarrierMessage = ErrorNotified = DontWorry = TypeChecked = FALSE;
  581.  
  582.         /* Reset transfer counters. */
  583.  
  584.     ByteVal = ByteMax = TimeVal = TimeMax = LastTimeDif = 0;
  585.  
  586.     LastPercent = -1;
  587.  
  588.         /* Reset CPS statistics. */
  589.  
  590.     CPS_Minimum    = (ULONG)~0;
  591.     CPS_Maximum    = 0;
  592.     CPS_Average    = 0;
  593.     CPS_Current    = 0;
  594.     CPS_Count    = 0;
  595.     CPS_Last    = 0;
  596.  
  597.         /* No window available for output? */
  598.  
  599.     if(!TransferWindow)
  600.         OpenTransferWindow();
  601.  
  602.     if(OriginalName[0])
  603.     {
  604.         if(!Stricmp(ShrunkenName,FileName))
  605.             FileName = OriginalName;
  606.     }
  607.  
  608.         /* Determine the file name. */
  609.  
  610.     FileName = NewFileName(FileName,RealName);
  611.  
  612.         /* Determine file transfer mode... */
  613.  
  614.     if(File = BufferOpen(FileName,AccessMode))
  615.     {
  616.         switch(AccessMode[0])
  617.         {
  618.             case 'r':
  619.  
  620.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_SEND_FILE_TXT),FileName);
  621.                 break;
  622.  
  623.             case 'w':
  624.  
  625.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_RECEIVE_FILE_TXT),FileName);
  626.                 break;
  627.  
  628.             case 'a':
  629.  
  630.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_UPDATE_FILE_TXT),FileName);
  631.                 break;
  632.         }
  633.  
  634.         CurrentFile = File;
  635.     }
  636.  
  637.     DidTransfer = TRUE;
  638.  
  639.     return((LONG)File);
  640. }
  641.  
  642.     /* xpr_fclose(struct Buffer *File):
  643.      *
  644.      *    Close a file opened by xpr_fopen.
  645.      */
  646.  
  647. LONG __saveds __asm
  648. xpr_fclose(REG(a0) struct Buffer *File)
  649. {
  650.     UBYTE                RealName[MAX_FILENAME_LENGTH];
  651.     struct DateStamp    OpenDate;
  652.     BOOL                WriteAccess,
  653.                         Used;
  654.  
  655.     DB(kprintf("xpr_fclose(0x%08lx)\n",File));
  656.  
  657.         /* This happened only once so far, but... */
  658.  
  659.     if(!File)
  660.     {
  661.         CurrentFile = NULL;
  662.  
  663.         return(1);
  664.     }
  665.  
  666.         /* Save some information. */
  667.  
  668.     OpenDate    = File->OpenDate;
  669.     WriteAccess    = File->WriteAccess;
  670.     Used        = File->Used;
  671.  
  672.         /* Get the name of the file. */
  673.  
  674.     if(!NameFromFH(File->FileHandle,RealName,MAX_FILENAME_LENGTH))
  675.         RealName[0] = 0;
  676.  
  677.         /* Close the file and see what it brings... */
  678.  
  679.     if(BufferClose(File) && RealName[0])
  680.     {
  681.             /* Did any access take place at all?
  682.              * xprzmodem.library for example just
  683.              * opens and closes a file in order to
  684.              * see if it exists.
  685.              */
  686.  
  687.         if(!Used)
  688.             LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  689.         else
  690.         {
  691.                 /* Did we receive or send a file? */
  692.  
  693.             if(WriteAccess)
  694.             {
  695.                 LONG Size;
  696.  
  697.                     /* Did the file remain empty? */
  698.  
  699.                 if(!(Size = GetFileSize(RealName)))
  700.                 {
  701.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_FILE_REMOVED_TXT),FilePart(RealName));
  702.  
  703.                         /* Delete empty file. */
  704.  
  705.                     if(DeleteFile(RealName))
  706.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_REMOVED_TXT),RealName);
  707.                     else
  708.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  709.                 }
  710.                 else
  711.                 {
  712.                     struct Node *SomeNode;
  713.  
  714.                     if(ByteMax)
  715.                     {
  716.                         if(Size >= ByteMax)
  717.                             AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_RECEIVED_TXT),FilePart(RealName));
  718.                         else
  719.                             AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_INCOMPLETE_FILE_RECEIVED_TXT),FilePart(RealName));
  720.                     }
  721.  
  722.                         /* Try to identify the file type. */
  723.  
  724.                     switch(Config->TransferConfig->IdentifyFiles)
  725.                     {
  726.                         case IDENTIFY_IGNORE:
  727.  
  728.                             if(Config->MiscConfig->CreateIcons)
  729.                                 Identify(RealName,FALSE);
  730.  
  731.                             break;
  732.  
  733.                         case IDENTIFY_FILETYPE:
  734.  
  735.                             Identify(RealName,TRUE);
  736.                             break;
  737.  
  738.                         case IDENTIFY_SOURCE:
  739.  
  740.                             IdentifySource(RealName,CurrentBBSName,&OpenDate);
  741.  
  742.                             if(Config->MiscConfig->CreateIcons)
  743.                                 Identify(RealName,FALSE);
  744.  
  745.                             break;
  746.                     }
  747.  
  748.                     if(CPS_Minimum == (ULONG)~0)
  749.                         CPS_Minimum = 0;
  750.  
  751.                     if(CPS_Count == 0)
  752.                     {
  753.                         CPS_Average    = 0;
  754.                         CPS_Count    = 1;
  755.                     }
  756.  
  757.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_BYTES_TXT),RealName,Size,CPS_Minimum,CPS_Average / CPS_Count,CPS_Maximum);
  758.  
  759.                     if(SomeNode = CreateGenericListNode(0,RealName))
  760.                         AddGenericListNode(GenericListTable[GLIST_DOWNLOAD],SomeNode,ADD_GLIST_BOTTOM);
  761.                 }
  762.             }
  763.             else
  764.             {
  765.                     /* Set the archived bit on files we uploaded? */
  766.  
  767.                 if(Config->TransferConfig->SetArchivedBit)
  768.                 {
  769.                     struct FileInfoBlock *FileInfo;
  770.  
  771.                     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  772.                     {
  773.                         BPTR FileLock;
  774.  
  775.                             /* Get a lock on it. */
  776.  
  777.                         if(FileLock = Lock(RealName,ACCESS_READ))
  778.                         {
  779.                                 /* Examine the file. */
  780.  
  781.                             if(Examine(FileLock,FileInfo))
  782.                             {
  783.                                     /* Remove the lock. */
  784.  
  785.                                 UnLock(FileLock);
  786.  
  787.                                     /* Set the `archived' bit. */
  788.  
  789.                                 SetProtection(RealName,FileInfo->fib_Protection | FIBF_ARCHIVE);
  790.                             }
  791.                             else
  792.                                 UnLock(FileLock);
  793.                         }
  794.  
  795.                         FreeDosObject(DOS_FIB,FileInfo);
  796.                     }
  797.                 }
  798.  
  799.                 AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_SENT_TXT),FilePart(RealName));
  800.  
  801.                 LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  802.  
  803.                 RemoveUploadListItem(RealName);
  804.             }
  805.         }
  806.     }
  807.  
  808.     CurrentFile = NULL;
  809.  
  810.     return(1);
  811. }
  812.  
  813.     /* xpr_fread(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  814.      *
  815.      *    Read a few bytes from a file.
  816.      */
  817.  
  818. LONG __saveds __asm
  819. xpr_fread(REG(a0) APTR Buffer,REG(d0) LONG Size,REG(d1) LONG Count,REG(a1) struct Buffer *File)
  820. {
  821.     DB(kprintf("xpr_fread(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File));
  822.  
  823.     return(BufferRead(File,Buffer,Size * Count) / Size);
  824. }
  825.  
  826.     /* xpr_fwrite(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  827.      *
  828.      *    Write a few bytes to a file.
  829.      */
  830.  
  831. LONG __saveds __asm
  832. xpr_fwrite(REG(a0) APTR Buffer,REG(d0) LONG Size,REG(d1) LONG Count,REG(a1) struct Buffer *File)
  833. {
  834.     DB(kprintf("xpr_fwrite(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File));
  835.  
  836.     return(BufferWrite(File,Buffer,Size * Count) / Size);
  837. }
  838.  
  839.     /* xpr_fseek(struct Buffer *File,LONG Offset,LONG Origin):
  840.      *
  841.      *    Move the read/write pointer in a file.
  842.      */
  843.  
  844. LONG __saveds __asm
  845. xpr_fseek(REG(a0) struct Buffer *File,REG(d0) LONG Offset,REG(d1) LONG Origin)
  846. {
  847.     DB(kprintf("xpr_fseek(0x%08lx,%ld,%ld)\n",File,Offset,Origin));
  848.  
  849.     return(BufferSeek(File,Offset,Origin) ? 0 : -1);
  850. }
  851.  
  852.     /* xpr_sread(APTR Buffer,LONG Size,LONG Timeout):
  853.      *
  854.      *    Read a few bytes from the serial port (including
  855.      *    timeouts).
  856.      */
  857.  
  858. LONG __saveds __asm
  859. xpr_sread(REG(a0) APTR Buffer,REG(d0) LONG Size,REG(d1) ULONG Timeout)
  860. {
  861.     DB(kprintf("xpr_sread(0x%08lx,%ld,%ld)\n",Buffer,Size,Timeout));
  862.  
  863.         /* No window available for output? */
  864.  
  865.     if(!TransferWindow)
  866.     {
  867.         if(!OpenTransferWindow())
  868.             return(-1);
  869.     }
  870.  
  871.         /* Are both IORequests available? */
  872.  
  873.     if(WriteRequest && ReadRequest)
  874.     {
  875.             /* Valid size parameter? */
  876.  
  877.         if(Size > 0)
  878.         {
  879.             ULONG    Waiting;
  880.             UWORD    Status;
  881.  
  882.             GetSerialInfo(&Waiting,&Status);
  883.  
  884.                 /* Return error if carrier is lost. */
  885.  
  886.             if(Config->SerialConfig->CheckCarrier && !Config->SerialConfig->DirectConnection)
  887.             {
  888.                 if(Status & CIAF_COMCD)
  889.                 {
  890.                     if(!CarrierMessage)
  891.                     {
  892.                         CarrierMessage = TRUE;
  893.  
  894.                         AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  895.                     }
  896.  
  897.                     SetOnlineState(FALSE);
  898.  
  899.                     TransferError = TRUE;
  900.  
  901.                     return(-1);
  902.                 }
  903.             }
  904.  
  905.             /* ALWAYS */
  906.             {
  907.                 if(Waiting)
  908.                 {
  909.                         /* No timeout specified? Read as many
  910.                          * bytes as available.
  911.                          */
  912.  
  913.                     if(!Timeout)
  914.                     {
  915.                         if(Waiting > Size)
  916.                             Waiting = Size;
  917.  
  918.                         if(DoSerialRead(Buffer,Waiting))
  919.                         {
  920.                             if(SerialErrorReport(ReadRequest))
  921.                                 return(-1);
  922.                             else
  923.                                 Waiting = ReadRequest->IOSer.io_Actual;
  924.                         }
  925.  
  926.                         BytesIn += Waiting;
  927.  
  928.                         return((LONG)Waiting);
  929.                     }
  930.  
  931.                         /* Enough data pending to be read? */
  932.  
  933.                     if(Waiting >= Size)
  934.                     {
  935.                         if(DoSerialRead(Buffer,Size))
  936.                         {
  937.                             if(SerialErrorReport(ReadRequest))
  938.                                 return(-1);
  939.                             else
  940.                                 Size = ReadRequest->IOSer.io_Actual;
  941.                         }
  942.  
  943.                         BytesIn += Size;
  944.  
  945.                         return(Size);
  946.                     }
  947.                 }
  948.                 else
  949.                 {
  950.                         /* No timeout & no bytes available:
  951.                          * return immediately.
  952.                          */
  953.  
  954.                     if(!Timeout)
  955.                         return(0);
  956.                 }
  957.             }
  958.  
  959.             /* ALWAYS */
  960.             {
  961.                 register ULONG    SignalSet,
  962.                                 SerialMask = PORTMASK(ReadPort),
  963.                                 WindowMask = PORTMASK(TransferWindow->UserPort);
  964.  
  965.                     /* Set up the timer. */
  966.  
  967.                 TimeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  968.                 TimeRequest->tr_time.tv_secs    = Timeout / MILLION;
  969.                 TimeRequest->tr_time.tv_micro    = Timeout % MILLION;
  970.  
  971.                     /* Prevent early termination. */
  972.  
  973.                 ClrSignal(SerialMask | SIG_TIMER);
  974.  
  975.                     /* Start IO... */
  976.  
  977.                 SendIO(TimeRequest);
  978.  
  979.                     /* Set up the read request. */
  980.  
  981.                 StartSerialRead(Buffer,Size);
  982.  
  983.                 FOREVER
  984.                 {
  985.                     SignalSet = Wait(SerialMask | SIG_TIMER | WindowMask);
  986.  
  987.                         /* Abort file transfer? */
  988.  
  989.                     if(SignalSet & WindowMask)
  990.                     {
  991.                         LONG Result = CheckAbort(FALSE);
  992.  
  993.                             /* Let's get out of here
  994.                              * and hope that the protocol
  995.                              * will call xpr_chkabort()
  996.                              * in time.
  997.                              */
  998.  
  999.                         if(Result)
  1000.                         {
  1001.                             if(TransferAbortState != Result)
  1002.                                 TransferAbortState = Result;
  1003.  
  1004.                                 /* Does the user want to cancel
  1005.                                  * the transmission?
  1006.                                  */
  1007.  
  1008.                             if(Result < 0)
  1009.                             {
  1010.                                     // Do it the hard way
  1011.  
  1012.                                 if(TransferAbortCount++)
  1013.                                 {
  1014.                                     StopSerialRead();
  1015.  
  1016.                                     if(!CheckIO(TimeRequest))
  1017.                                         AbortIO(TimeRequest);
  1018.  
  1019.                                     WaitIO(TimeRequest);
  1020.  
  1021.                                         // Oh Janet, don't tell me to can it
  1022.  
  1023.                                     DoSerialWrite(ZModemCancel,20);
  1024.  
  1025.                                     return(Result);
  1026.                                 }
  1027.                             }
  1028.  
  1029.                                 /* Abort the read request. */
  1030.  
  1031.                             StopSerialRead();
  1032.  
  1033.                                 /* Remove the timer request. */
  1034.  
  1035.                             if(!CheckIO(TimeRequest))
  1036.                                 AbortIO(TimeRequest);
  1037.  
  1038.                             WaitIO(TimeRequest);
  1039.  
  1040.                                 /* Did the driver receive any
  1041.                                  * data?
  1042.                                  */
  1043.  
  1044.                             if(ReadRequest->IOSer.io_Actual)
  1045.                             {
  1046.                                 BytesIn += ReadRequest->IOSer.io_Actual;
  1047.  
  1048.                                 return((LONG)ReadRequest->IOSer.io_Actual);
  1049.                             }
  1050.                             else
  1051.                             {
  1052.                                     /* Take a second look and query the number of
  1053.                                      * bytes ready to be received, there may
  1054.                                      * still be some bytes in the buffer.
  1055.                                      * Note: this depends on the way the
  1056.                                      * driver handles read abort.
  1057.                                      */
  1058.  
  1059.                                 Waiting = GetSerialWaiting();
  1060.  
  1061.                                     /* Don't read too much. */
  1062.  
  1063.                                 if(Size > Waiting)
  1064.                                     Size = Waiting;
  1065.  
  1066.                                     /* Are there any bytes to be transferred? */
  1067.  
  1068.                                 if(Size)
  1069.                                 {
  1070.                                         /* Read the data. */
  1071.  
  1072.                                     if(DoSerialRead(Buffer,Size))
  1073.                                     {
  1074.                                         if(SerialErrorReport(ReadRequest))
  1075.                                             return(-1);
  1076.                                         else
  1077.                                             Size = ReadRequest->IOSer.io_Actual;
  1078.                                     }
  1079.  
  1080.                                     BytesIn += Size;
  1081.                                 }
  1082.  
  1083.                                 return(Size);
  1084.                             }
  1085.                         }
  1086.                     }
  1087.  
  1088.                         /* Receive buffer filled? */
  1089.  
  1090.                     if(SignalSet & SerialMask)
  1091.                     {
  1092.                             /* Abort the timer request. */
  1093.  
  1094.                         if(!CheckIO(TimeRequest))
  1095.                             AbortIO(TimeRequest);
  1096.  
  1097.                         WaitIO(TimeRequest);
  1098.  
  1099.                             /* Did the request terminate gracefully? */
  1100.  
  1101.                         if(WaitSerialRead())
  1102.                         {
  1103.                             if(SerialErrorReport(ReadRequest))
  1104.                                 return(-1);
  1105.                             else
  1106.                                 Size = ReadRequest->IOSer.io_Actual;
  1107.                         }
  1108.  
  1109.                         BytesIn += Size;
  1110.  
  1111.                         return(Size);
  1112.                     }
  1113.  
  1114.                         /* Hit by timeout? */
  1115.  
  1116.                     if(SignalSet & SIG_TIMER)
  1117.                     {
  1118.                             /* Abort the read request. */
  1119.  
  1120.                         StopSerialRead();
  1121.  
  1122.                             /* Remove the timer request. */
  1123.  
  1124.                         WaitIO(TimeRequest);
  1125.  
  1126.                             /* Did the driver receive any
  1127.                              * data?
  1128.                              */
  1129.  
  1130.                         if(ReadRequest->IOSer.io_Actual)
  1131.                         {
  1132.                             BytesIn += ReadRequest->IOSer.io_Actual;
  1133.  
  1134.                             return((LONG)ReadRequest->IOSer.io_Actual);
  1135.                         }
  1136.                         else
  1137.                         {
  1138.                                 /* Take a second look and query the number of
  1139.                                  * bytes ready to be received, there may
  1140.                                  * still be some bytes in the buffer.
  1141.                                  * Note: this depends on the way the
  1142.                                  * driver handles read abort.
  1143.                                  */
  1144.  
  1145.                             Waiting = GetSerialWaiting();
  1146.  
  1147.                                 /* Don't read too much. */
  1148.  
  1149.                             if(Size > Waiting)
  1150.                                 Size = Waiting;
  1151.  
  1152.                                 /* Are there any bytes to be transferred? */
  1153.  
  1154.                             if(Size)
  1155.                             {
  1156.                                     /* Read the data. */
  1157.  
  1158.                                 if(DoSerialRead(Buffer,Size))
  1159.                                 {
  1160.                                     if(SerialErrorReport(ReadRequest))
  1161.                                         return(-1);
  1162.                                     else
  1163.                                         Size = ReadRequest->IOSer.io_Actual;
  1164.                                 }
  1165.  
  1166.                                 BytesIn += Size;
  1167.                             }
  1168.  
  1169.                             return(Size);
  1170.                         }
  1171.                     }
  1172.                 }
  1173.             }
  1174.         }
  1175.         else
  1176.             return(0);
  1177.     }
  1178.     else
  1179.         return(-1);
  1180. }
  1181.  
  1182.     /* xpr_swrite(APTR Buffer,LONG Size):
  1183.      *
  1184.      *    Write a few bytes to the serial port.
  1185.      */
  1186.  
  1187. LONG __saveds __asm
  1188. xpr_swrite(REG(a0) APTR Buffer,REG(d0) LONG Size)
  1189. {
  1190.     DB(kprintf("xpr_swrite(0x%08lx,%ld)\n",Buffer,Size));
  1191.  
  1192.     if(WriteRequest)
  1193.     {
  1194.             /* Return error if carrier is lost. */
  1195.  
  1196.         if(Config->SerialConfig->CheckCarrier && !Config->SerialConfig->DirectConnection)
  1197.         {
  1198.                 /* Is the carrier signal still present? */
  1199.  
  1200.             if(GetSerialStatus() & CIAF_COMCD)
  1201.             {
  1202.                 if(!CarrierMessage)
  1203.                 {
  1204.                     CarrierMessage = TRUE;
  1205.  
  1206.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  1207.                 }
  1208.  
  1209.                 SetOnlineState(FALSE);
  1210.  
  1211.                 TransferError = TRUE;
  1212.  
  1213.                 return(-1);
  1214.             }
  1215.         }
  1216.  
  1217.             /* Send the data. */
  1218.  
  1219.         if(DoSerialWrite(Buffer,Size))
  1220.         {
  1221.             if(SerialErrorReport(WriteRequest))
  1222.                 return(-1);
  1223.         }
  1224.         else
  1225.             BytesOut += Size;
  1226.  
  1227.         return(0);
  1228.     }
  1229.     else
  1230.         return(-1);
  1231. }
  1232.  
  1233.     /* xpr_sflush():
  1234.      *
  1235.      *    Release the contents of all serial buffers.
  1236.      */
  1237.  
  1238. LONG __saveds __asm
  1239. xpr_sflush()
  1240. {
  1241.     DB(kprintf("xpr_sflush()\n"));
  1242.  
  1243.     return((LONG)DoSerialCmd(CMD_CLEAR));
  1244. }
  1245.  
  1246.     /* xpr_update(struct XPR_UPDATE *UpdateInfo):
  1247.      *
  1248.      *    Update the information displayed in the transfer window.
  1249.      */
  1250.  
  1251. LONG __saveds __asm
  1252. xpr_update(REG(a0) struct XPR_UPDATE *UpdateInfo)
  1253. {
  1254.     DB(kprintf("xpr_update(0x%08lx)\n",UpdateInfo));
  1255.  
  1256.         /* No window available for output? */
  1257.  
  1258.     if(!TransferWindow)
  1259.     {
  1260.         if(!OpenTransferWindow())
  1261.             return(0);
  1262.     }
  1263.  
  1264.     if(UpdateInfo)
  1265.     {
  1266.         BOOL    NewByte = FALSE,
  1267.                 NewTime = FALSE;
  1268.  
  1269.         if(TransferWindow->Flags & WFLG_ZOOMED)
  1270.         {
  1271.             BOOLEAN Refresh;
  1272.  
  1273.             if(!TransferZoomed)
  1274.             {
  1275.                 ULONG Micros;
  1276.  
  1277.                 CurrentTime(&LastSeconds,&Micros);
  1278.  
  1279.                 Refresh = TRUE;
  1280.  
  1281.                 TransferZoomed = TRUE;
  1282.             }
  1283.             else
  1284.             {
  1285.                 ULONG Seconds,Micros;
  1286.  
  1287.                 CurrentTime(&Seconds,&Micros);
  1288.  
  1289.                 if(Seconds > LastSeconds)
  1290.                 {
  1291.                     LastSeconds = Seconds;
  1292.  
  1293.                     Refresh = TRUE;
  1294.                 }
  1295.             }
  1296.  
  1297.             if(Refresh)
  1298.             {
  1299.                 if(LastPercent > 0)
  1300.                     SPrintf(TransferTitleBuffer,"%s [%s %ld%%]",TransferWindowTitle,TruncateName(RealName),LastPercent);
  1301.                 else
  1302.                     SPrintf(TransferTitleBuffer,"%s [%s]",TransferWindowTitle,TruncateName(RealName));
  1303.  
  1304.                 SetWindowTitles(TransferWindow,TransferTitleBuffer,(STRPTR)-1);
  1305.             }
  1306.         }
  1307.         else
  1308.         {
  1309.             if(TransferZoomed)
  1310.             {
  1311.                 SetWindowTitles(TransferWindow,TransferWindowTitle,(STRPTR)-1);
  1312.  
  1313.                 TransferZoomed = FALSE;
  1314.             }
  1315.         }
  1316.  
  1317.         if((UpdateInfo->xpru_updatemask & XPRU_PROTOCOL) && UpdateInfo->xpru_protocol)
  1318.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_PROTOCOL,GTTX_Text,UpdateInfo->xpru_protocol,TAG_DONE);
  1319.  
  1320.         if((UpdateInfo->xpru_updatemask & XPRU_MSG) && UpdateInfo->xpru_msg)
  1321.             AddTransferInfo(FALSE,UpdateInfo->xpru_msg);
  1322.  
  1323.         if((UpdateInfo->xpru_updatemask & XPRU_ERRORMSG) && UpdateInfo->xpru_errormsg)
  1324.             AddTransferInfo(TRUE,UpdateInfo->xpru_errormsg);
  1325.  
  1326.         if((UpdateInfo->xpru_updatemask & XPRU_FILENAME) && UpdateInfo->xpru_filename)
  1327.         {
  1328.             STRPTR FileName = UpdateInfo->xpru_filename;
  1329.  
  1330.             if(OriginalName[0])
  1331.             {
  1332.                 if(!Stricmp(ShrunkenName,FileName))
  1333.                     FileName = OriginalName;
  1334.             }
  1335.  
  1336.             FileName = NewFileName(FileName,RealName);
  1337.  
  1338.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,0,LABX_Text,TruncateName(FileName),TAG_DONE);
  1339.  
  1340.             if(FileTransferInfo)
  1341.             {
  1342.                 if(FileTransferInfo->CurrentFile)
  1343.                 {
  1344.                     struct FileTransferNode *Node = (struct FileTransferNode *)FileTransferInfo->CurrentFile->Node.mln_Succ;
  1345.  
  1346.                     if(Node->Node.mln_Succ)
  1347.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,TruncateName(Node->Name),TAG_DONE);
  1348.                     else
  1349.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,LocaleString(MSG_GLOBAL_NONE_TXT),TAG_DONE);
  1350.                 }
  1351.  
  1352.                 PrintBox(GAD_TRANSFER_SIZE,2,ConvNumber,FileTransferInfo->TotalSize);
  1353.  
  1354.                 if(FileTransferInfo->TotalFiles)
  1355.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo->DoneFiles,FileTransferInfo->TotalFiles,(100 * FileTransferInfo->DoneFiles) / FileTransferInfo->TotalFiles);
  1356.                 else
  1357.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo->DoneFiles,FileTransferInfo->TotalFiles,0);
  1358.             }
  1359.         }
  1360.  
  1361.         if((UpdateInfo->xpru_updatemask & XPRU_FILESIZE) && UpdateInfo->xpru_filesize != -1)
  1362.         {
  1363.             if(CurrentFile)
  1364.             {
  1365.                 if(CurrentFile->InfoPort)
  1366.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber10,UpdateInfo->xpru_filesize);
  1367.                 else
  1368.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo->xpru_filesize);
  1369.             }
  1370.             else
  1371.                 PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo->xpru_filesize);
  1372.  
  1373.             if(ByteMax = UpdateInfo->xpru_filesize)
  1374.                 NewByte = TRUE;
  1375.         }
  1376.  
  1377.         if((UpdateInfo->xpru_updatemask & XPRU_BYTES) && UpdateInfo->xpru_bytes != -1)
  1378.         {
  1379.             if(CurrentFile)
  1380.             {
  1381.                 if(CurrentFile->InfoPort)
  1382.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber10,ByteVal = UpdateInfo->xpru_bytes);
  1383.                 else
  1384.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo->xpru_bytes);
  1385.             }
  1386.             else
  1387.                 PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo->xpru_bytes);
  1388.  
  1389.             if(FileTransferInfo)
  1390.             {
  1391.                 ULONG Len = FileTransferInfo->DoneSize + UpdateInfo->xpru_bytes;
  1392.  
  1393.                 if(FileTransferInfo->TotalSize)
  1394.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,(100 * Len) / FileTransferInfo->TotalSize);
  1395.                 else
  1396.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,0);
  1397.             }
  1398.  
  1399.             if(ByteMax)
  1400.                 NewByte = TRUE;
  1401.  
  1402.             if(CurrentFile)
  1403.             {
  1404.                 if(CurrentFile->InfoPort && !Uploading)
  1405.                 {
  1406.                     if(CurrentFile->InfoData.id_NumBlocks && CurrentFile->InfoData.id_BytesPerBlock)
  1407.                     {
  1408.                         if(ByteMax)
  1409.                         {
  1410.                             register LONG Space = CurrentFile->InfoData.id_NumBlocks - CurrentFile->InfoData.id_NumBlocksUsed;
  1411.  
  1412.                             if(Space >= 0)
  1413.                             {
  1414.                                     // Important! Only use the number of bytes still
  1415.                                     // to be transferred.
  1416.  
  1417.                                 register LONG Blocks = CalculateBlocks(ByteMax - ByteVal,CurrentFile->InfoData.id_BytesPerBlock);
  1418.  
  1419.                                     // Did we take a look at the filing system yet?
  1420.  
  1421.                                 if(!TypeChecked)
  1422.                                 {
  1423.                                         // If this is not a block mapped device
  1424.                                         // we cannot guess what will happen if
  1425.                                         // it fills up (and whether it fills up at all).
  1426.  
  1427.                                     if(!IsBlockMappedDevice(CurrentFile->InfoPort))
  1428.                                         DontWorry = TRUE;
  1429.  
  1430.                                         // Ok, done
  1431.  
  1432.                                     TypeChecked = TRUE;
  1433.                                 }
  1434.  
  1435.                                 if(Space >= Blocks || DontWorry)
  1436.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile->InfoData.id_BytesPerBlock,100 * (CurrentFile->InfoData.id_NumBlocksUsed) / CurrentFile->InfoData.id_NumBlocks,"");
  1437.                                 else
  1438.                                 {
  1439.                                     if(!Alerted)
  1440.                                     {
  1441.                                         Alerted = TRUE;
  1442.  
  1443.                                         Say(LocaleString(MSG_TERMXPR_SAY_FILE_MAY_NOT_FIT_TXT));
  1444.                                     }
  1445.  
  1446.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile->InfoData.id_BytesPerBlock,100 * (CurrentFile->InfoData.id_NumBlocksUsed) / CurrentFile->InfoData.id_NumBlocks,LocaleString(MSG_TERMXPR_FILE_MAY_NOT_FIT_TXT));
  1447.                                 }
  1448.                             }
  1449.                             else
  1450.                                 PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile->InfoData.id_NumBlocks - CurrentFile->InfoData.id_NumBlocksUsed) * CurrentFile->InfoData.id_BytesPerBlock,100 * (CurrentFile->InfoData.id_NumBlocksUsed) / CurrentFile->InfoData.id_NumBlocks);
  1451.                         }
  1452.                         else
  1453.                             PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile->InfoData.id_NumBlocks - CurrentFile->InfoData.id_NumBlocksUsed) * CurrentFile->InfoData.id_BytesPerBlock,100 * (CurrentFile->InfoData.id_NumBlocksUsed) / CurrentFile->InfoData.id_NumBlocks);
  1454.                     }
  1455.                 }
  1456.             }
  1457.         }
  1458.  
  1459.         if((UpdateInfo->xpru_updatemask & XPRU_BLOCKS) && UpdateInfo->xpru_blocks != -1)
  1460.             PrintBox(GAD_TRANSFER_SIZE,5,ConvNumber,UpdateInfo->xpru_blocks);
  1461.  
  1462.         if((UpdateInfo->xpru_updatemask & XPRU_DATARATE) && UpdateInfo->xpru_datarate > 0)
  1463.         {
  1464.             register LONG Change;
  1465.  
  1466.             CPS_Current = UpdateInfo->xpru_datarate;
  1467.  
  1468.             if(CPS_Last)
  1469.             {
  1470.                 if(CPS_Last < UpdateInfo->xpru_datarate)
  1471.                     Change = (100 * (UpdateInfo->xpru_datarate - CPS_Last)) / CPS_Last;
  1472.                 else
  1473.                     Change = (100 * (CPS_Last - UpdateInfo->xpru_datarate)) / CPS_Last;
  1474.             }
  1475.             else
  1476.                 Change = 100;
  1477.  
  1478.             if(Change > 1)
  1479.             {
  1480.                 PrintBox(GAD_TRANSFER_SECONDS,0,ConvNumber,UpdateInfo->xpru_datarate);
  1481.  
  1482.                 CPS_Last = UpdateInfo->xpru_datarate;
  1483.             }
  1484.  
  1485.             if(UpdateInfo->xpru_datarate < CPS_Minimum)
  1486.                 CPS_Minimum = UpdateInfo->xpru_datarate;
  1487.  
  1488.             if(UpdateInfo->xpru_datarate > CPS_Maximum)
  1489.                 CPS_Maximum = UpdateInfo->xpru_datarate;
  1490.  
  1491.             if((ULONG)(CPS_Average + UpdateInfo->xpru_datarate) >= CPS_Average)
  1492.             {
  1493.                 CPS_Average += UpdateInfo->xpru_datarate;
  1494.  
  1495.                 CPS_Count++;
  1496.             }
  1497.         }
  1498.  
  1499.         if((UpdateInfo->xpru_updatemask & XPRU_CHARDELAY) && UpdateInfo->xpru_chardelay != -1)
  1500.             PrintBox(GAD_TRANSFER_SECONDS,1,ConvNumber,UpdateInfo->xpru_chardelay);
  1501.  
  1502.         if((UpdateInfo->xpru_updatemask & XPRU_PACKETDELAY) && UpdateInfo->xpru_packetdelay != -1)
  1503.             PrintBox(GAD_TRANSFER_SECONDS,2,ConvNumber,UpdateInfo->xpru_packetdelay);
  1504.  
  1505.         if((UpdateInfo->xpru_updatemask & XPRU_PACKETTYPE) && UpdateInfo->xpru_packettype != -1)
  1506.         {
  1507.             if(UpdateInfo->xpru_packettype > 32 && UpdateInfo->xpru_packettype < 256)
  1508.             {
  1509.                 if(IsPrintable[UpdateInfo->xpru_packettype])
  1510.                     PrintBox(GAD_TRANSFER_SECONDS,3,"`%lc'",UpdateInfo->xpru_packettype);
  1511.                 else
  1512.                     PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo->xpru_packettype);
  1513.             }
  1514.             else
  1515.                 PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo->xpru_packettype);
  1516.         }
  1517.  
  1518.         if((UpdateInfo->xpru_updatemask & XPRU_BLOCKCHECK) && UpdateInfo->xpru_blockcheck)
  1519.             PrintBox(GAD_TRANSFER_SECONDS,4,UpdateInfo->xpru_blockcheck);
  1520.  
  1521.         if((UpdateInfo->xpru_updatemask & XPRU_BLOCKSIZE) && UpdateInfo->xpru_blocksize != -1)
  1522.             PrintBox(GAD_TRANSFER_SECONDS,5,ConvNumber,UpdateInfo->xpru_blocksize);
  1523.  
  1524.  
  1525.         if((UpdateInfo->xpru_updatemask & XPRU_EXPECTTIME) && UpdateInfo->xpru_expecttime)
  1526.         {
  1527.             PrintBox(GAD_TRANSFER_TOTALTIME,0,UpdateInfo->xpru_expecttime);
  1528.  
  1529.             if(TimeMax = GetSeconds((STRPTR)UpdateInfo->xpru_expecttime))
  1530.                 NewTime = TRUE;
  1531.         }
  1532.  
  1533.         if((UpdateInfo->xpru_updatemask & XPRU_ELAPSEDTIME) && UpdateInfo->xpru_elapsedtime)
  1534.         {
  1535.             PrintBox(GAD_TRANSFER_TOTALTIME,1,UpdateInfo->xpru_elapsedtime);
  1536.  
  1537.             TimeVal = GetSeconds((STRPTR)UpdateInfo->xpru_elapsedtime);
  1538.  
  1539.             if(TimeMax)
  1540.                 NewTime = TRUE;
  1541.         }
  1542.  
  1543.         if((UpdateInfo->xpru_updatemask & XPRU_ERRORS) && UpdateInfo->xpru_errors != -1)
  1544.         {
  1545.             PrintBox(GAD_TRANSFER_ERRORS,0,ConvNumber,UpdateInfo->xpru_errors);
  1546.  
  1547.             if(!ErrorNotified && Config->TransferConfig->ErrorNotification && UpdateInfo->xpru_errors >= Config->TransferConfig->ErrorNotification)
  1548.             {
  1549.                 ErrorNotified = TRUE;
  1550.  
  1551.                 WakeUp(TransferWindow,SOUND_ERROR);
  1552.             }
  1553.         }
  1554.  
  1555.         if((UpdateInfo->xpru_updatemask & XPRU_TIMEOUTS) && UpdateInfo->xpru_timeouts != -1)
  1556.             PrintBox(GAD_TRANSFER_ERRORS,1,ConvNumber,UpdateInfo->xpru_timeouts);
  1557.  
  1558.         if(NewByte)
  1559.         {
  1560.             LONG Percent;
  1561.  
  1562.             if(ByteMax)
  1563.                 Percent = (100 * ByteVal) / ByteMax;
  1564.             else
  1565.                 Percent = 0;
  1566.  
  1567.             if(Percent != LastPercent)
  1568.             {
  1569.                 UBYTE LocalBuffer[40];
  1570.  
  1571.                 SPrintf(LocalBuffer,"%ld%% %s",Percent,LocaleString(MSG_TRANSFERPANEL_DATA_TRANSFERRED_GAD));
  1572.  
  1573.                 LastPercent = Percent;
  1574.  
  1575.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_PERCENT,
  1576.                     LAGA_Percent,    Percent,
  1577.                     LAGA_InfoText,    LocalBuffer,
  1578.                 TAG_DONE);
  1579.             }
  1580.         }
  1581.  
  1582.         if(NewTime)
  1583.         {
  1584.             register LONG TimeDif,Change;
  1585.  
  1586.             if(TimeVal > TimeMax)
  1587.                 TimeDif = 0;
  1588.             else
  1589.                 TimeDif = TimeMax - TimeVal;
  1590.  
  1591.             if(LastTimeDif)
  1592.             {
  1593.                 if(LastTimeDif < TimeDif)
  1594.                     Change = (100 * (TimeDif - LastTimeDif)) / LastTimeDif;
  1595.                 else
  1596.                     Change = (100 * (LastTimeDif - TimeDif)) / LastTimeDif;
  1597.             }
  1598.             else
  1599.                 Change = 100;
  1600.  
  1601.                 /* Don't update the display unless the change
  1602.                  * exceeds 2% of the previous value.
  1603.                  */
  1604.  
  1605.             if(Change > 2)
  1606.             {
  1607.                 UBYTE    LocalBuffer[40];
  1608.                 LONG    Percent;
  1609.  
  1610.                 LastTimeDif = TimeDif;
  1611.  
  1612.                 if(TimeMax)
  1613.                     Percent = (100 * TimeDif) / TimeMax;
  1614.                 else
  1615.                     Percent = 0;
  1616.  
  1617.                 SPrintf(LocalBuffer,"%2ld:%02ld:%02ld %s",TimeDif / 3600,(TimeDif / 60) % 60,TimeDif % 60,LocaleString(MSG_TRANSFERPANEL_TIME_TO_GO_GAD));
  1618.  
  1619.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_TIME,
  1620.                     LAGA_Percent,    Percent,
  1621.                     LAGA_InfoText,    LocalBuffer,
  1622.                 TAG_DONE);
  1623.  
  1624.                     /* A rapidly changing transfer time display would
  1625.                      * cause the transfer completion time display to
  1626.                      * change at the same pace. As the completion time
  1627.                      * display calculation is rather costly, a change smaller
  1628.                      * than 5% of the previous value is silently ignored.
  1629.                      */
  1630.  
  1631.                 if(Change > 5)
  1632.                 {
  1633.                     UBYTE            DateTimeBuffer[256];
  1634.                     struct DateStamp    Stamp;
  1635.  
  1636.                         /* Obtain current time. */
  1637.  
  1638.                     DateStamp(&Stamp);
  1639.  
  1640.                         /* Add the time to go. */
  1641.  
  1642.                     Stamp.ds_Tick        += (TimeDif % 60) * TICKS_PER_SECOND;
  1643.                     Stamp.ds_Minute    += TimeDif / 60 + Stamp.ds_Tick / (60 * TICKS_PER_SECOND);
  1644.                     Stamp.ds_Days        += Stamp.ds_Minute / 1440;
  1645.  
  1646.                     Stamp.ds_Tick        %= 60 * TICKS_PER_SECOND;
  1647.                     Stamp.ds_Minute    %= 1440;
  1648.  
  1649.                         /* Conversion succeeded? */
  1650.  
  1651.                     if(FormatStamp(&Stamp,NULL,NULL,DateTimeBuffer,TRUE))
  1652.                         PrintBox(GAD_TRANSFER_FILE,3,DateTimeBuffer);
  1653.                 }
  1654.             }
  1655.         }
  1656.     }
  1657.  
  1658.     return(1);
  1659. }
  1660.  
  1661.     /* xpr_chkabort():
  1662.      *
  1663.      *    Check if the user has aborted the transfer.
  1664.      */
  1665.  
  1666. LONG __saveds __asm
  1667. xpr_chkabort()
  1668. {
  1669.     LONG Result;
  1670.  
  1671.     DB(kprintf("xpr_chkabort()\n"));
  1672.  
  1673.     if(TransferAbortState != 0)
  1674.     {
  1675.         Result = TransferAbortState;
  1676.  
  1677.         TransferAbortState = 0;
  1678.     }
  1679.     else
  1680.         Result = CheckAbort(Config->SerialConfig->CheckCarrier && !Config->SerialConfig->DirectConnection);
  1681.  
  1682.     return(Result);
  1683. }
  1684.  
  1685.     /* xpr_gets(STRPTR Prompt,STRPTR Buffer):
  1686.      *
  1687.      *    Prompt the user for string input.
  1688.      */
  1689.  
  1690. LONG __saveds __asm
  1691. xpr_gets(REG(a0) STRPTR Prompt,REG(a1) STRPTR Buffer)
  1692. {
  1693.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1694.  
  1695.     LayoutHandle    *Handle;
  1696.     LONG             Success = FALSE;
  1697.     UBYTE             LocalBuffer[256];
  1698.  
  1699.     DB(kprintf("xpr_gets(\"%s\",\"%s\")\n",Prompt,Buffer));
  1700.  
  1701.     if(strlen(Buffer) > 255)
  1702.     {
  1703.         CopyMem(Buffer,LocalBuffer,255);
  1704.  
  1705.         LocalBuffer[255] = 0;
  1706.     }
  1707.     else
  1708.         strcpy(LocalBuffer,Buffer);
  1709.  
  1710.     if(!Prompt)
  1711.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1712.  
  1713.     if(Handle = LT_CreateHandleTags(Window->WScreen,
  1714.         LH_LocaleHook,    &LocaleHook,
  1715.     TAG_DONE))
  1716.     {
  1717.         struct Window *PanelWindow;
  1718.  
  1719.         LT_New(Handle,
  1720.             LA_Type,VERTICAL_KIND,
  1721.         TAG_DONE);
  1722.         {
  1723.             LT_New(Handle,
  1724.                 LA_Type,        VERTICAL_KIND,
  1725.                 LA_LabelText,    Prompt,
  1726.             TAG_DONE);
  1727.             {
  1728.                 LT_New(Handle,
  1729.                     LA_Type,    STRING_KIND,
  1730.                     LA_STRPTR,    LocalBuffer,
  1731.                     LA_ID,        GAD_STRING,
  1732.                     LA_Chars,    30,
  1733.                 TAG_DONE);
  1734.  
  1735.                 LT_EndGroup(Handle);
  1736.             }
  1737.  
  1738.             LT_New(Handle,
  1739.                 LA_Type,VERTICAL_KIND,
  1740.             TAG_DONE);
  1741.             {
  1742.                 LT_New(Handle,
  1743.                     LA_Type,        XBAR_KIND,
  1744.                     LAXB_FullSize,    TRUE,
  1745.                 TAG_DONE);
  1746.  
  1747.                 LT_EndGroup(Handle);
  1748.             }
  1749.  
  1750.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1751.                 LAGR_SameSize,    TRUE,
  1752.                 LAGR_Spread,    TRUE,
  1753.             TAG_DONE);
  1754.             {
  1755.                 LT_New(Handle,
  1756.                     LA_Type,        BUTTON_KIND,
  1757.                     LA_LabelID,        MSG_TERMXPR_OKAY_GAD,
  1758.                     LA_ID,            GAD_OK,
  1759.                     LABT_ReturnKey,    TRUE,
  1760.                     LABT_ExtraFat,    TRUE,
  1761.                 TAG_DONE);
  1762.  
  1763.                 LT_New(Handle,
  1764.                     LA_Type,        BUTTON_KIND,
  1765.                     LA_LabelID,        MSG_GLOBAL_CANCEL_GAD,
  1766.                     LA_ID,            GAD_CANCEL,
  1767.                     LABT_EscKey,    TRUE,
  1768.                     LABT_ExtraFat,    TRUE,
  1769.                 TAG_DONE);
  1770.  
  1771.                 LT_EndGroup(Handle);
  1772.             }
  1773.         }
  1774.  
  1775.         if(PanelWindow = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1776.             LAWN_HelpHook,        &GuideHook,
  1777.             LAWN_Parent,        Window,
  1778.             WA_DepthGadget,        TRUE,
  1779.             WA_CloseGadget,        TRUE,
  1780.             WA_DragBar,            TRUE,
  1781.             WA_RMBTrap,            TRUE,
  1782.             WA_Activate,        TRUE,
  1783.         TAG_DONE))
  1784.         {
  1785.             struct IntuiMessage    *Message;
  1786.             BOOLEAN                 Done = FALSE;
  1787.             ULONG                 MsgClass,
  1788.                                  MsgQualifier;
  1789.             UWORD                 MsgCode;
  1790.             struct Gadget        *MsgGadget;
  1791.  
  1792.             PushWindow(PanelWindow);
  1793.  
  1794.             LT_ShowWindow(Handle,TRUE);
  1795.  
  1796.             LT_Activate(Handle,GAD_STRING);
  1797.  
  1798.             do
  1799.             {
  1800.                 if(Wait(PORTMASK(PanelWindow->UserPort) | SIG_BREAK) & SIG_BREAK)
  1801.                     break;
  1802.  
  1803.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow->UserPort))
  1804.                 {
  1805.                     MsgClass        = Message->Class;
  1806.                     MsgQualifier    = Message->Qualifier;
  1807.                     MsgCode            = Message->Code;
  1808.                     MsgGadget        = (struct Gadget *)Message->IAddress;
  1809.  
  1810.                     GT_ReplyIMsg(Message);
  1811.  
  1812.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1813.  
  1814.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1815.                         Done = TRUE;
  1816.  
  1817.                     if(MsgClass == IDCMP_GADGETUP)
  1818.                     {
  1819.                         switch(MsgGadget->GadgetID)
  1820.                         {
  1821.                             case GAD_STRING:
  1822.  
  1823.                                 if(MsgCode == '\r')
  1824.                                 {
  1825.                                     if(strcmp(Buffer,LocalBuffer))
  1826.                                         NewOptions = TRUE;
  1827.  
  1828.                                     strcpy(Buffer,LocalBuffer);
  1829.  
  1830.                                     Success = Done = TRUE;
  1831.  
  1832.                                     LT_PressButton(Handle,GAD_OK);
  1833.                                 }
  1834.  
  1835.                                 break;
  1836.  
  1837.                             case GAD_OK:
  1838.  
  1839.                                 LT_UpdateStrings(Handle);
  1840.  
  1841.                                 if(strcmp(Buffer,LocalBuffer))
  1842.                                     NewOptions = TRUE;
  1843.  
  1844.                                 strcpy(Buffer,LocalBuffer);
  1845.  
  1846.                                 Success = Done = TRUE;
  1847.  
  1848.                                 break;
  1849.  
  1850.                             case GAD_CANCEL:
  1851.  
  1852.                                 Done = TRUE;
  1853.                                 break;
  1854.                         }
  1855.                     }
  1856.                 }
  1857.             }
  1858.             while(!Done);
  1859.  
  1860.             PopWindow();
  1861.         }
  1862.  
  1863.         LT_DeleteHandle(Handle);
  1864.     }
  1865.  
  1866.     return(Success);
  1867. }
  1868.  
  1869.     /* xpr_setserial(LONG Status):
  1870.      *
  1871.      *    Set/read the serial status (parameters).
  1872.      */
  1873.  
  1874. LONG __saveds __asm
  1875. xpr_setserial(REG(d0) LONG Status)
  1876. {
  1877.     DB(kprintf("xpr_setserial(0x%08lx)\n",Status));
  1878.  
  1879.     if(WriteRequest)
  1880.     {
  1881.         STATIC LONG XprBauds[12] =
  1882.         {
  1883.                110,
  1884.                300,
  1885.               1200,
  1886.               2400,
  1887.               4800,
  1888.               9600,
  1889.              19200,
  1890.              31250,
  1891.              38400,
  1892.              57600,
  1893.              76800,
  1894.             115200
  1895.         };
  1896.  
  1897.         LONG Return,i;
  1898.  
  1899.         StopSerialRead();
  1900.         StopSerialWrite();
  1901.  
  1902.         DoSerialCmd(SDCMD_QUERY);
  1903.  
  1904.         Return = WriteRequest->io_SerFlags & 0xFF;
  1905.  
  1906.         if(WriteRequest->io_ExtFlags & SEXTF_MSPON)
  1907.             Return |= ST_PARTYMARKON;
  1908.  
  1909.         if(WriteRequest->io_ExtFlags & SEXTF_MARK)
  1910.             Return |= ST_PARTYMARK;
  1911.  
  1912.         if(WriteRequest->io_StopBits == 2)
  1913.             Return |= ST_2BITS;
  1914.  
  1915.         if(WriteRequest->io_ReadLen == 7)
  1916.             Return |= ST_READ7;
  1917.  
  1918.         if(WriteRequest->io_WriteLen == 7)
  1919.             Return |= ST_WRITE7;
  1920.  
  1921.         for(i = 0 ; i < 12 ; i++)
  1922.         {
  1923.             if(XprBauds[i] >= WriteRequest->io_Baud)
  1924.             {
  1925.                 Return |= (i << 16);
  1926.  
  1927.                 break;
  1928.             }
  1929.         }
  1930.  
  1931.             // Just in case no match was to be made...
  1932.  
  1933.         if(!(Return & 0xFFFF0000))
  1934.             Return |= (11 << 16);
  1935.  
  1936.             /* Update serial parameters, don't change
  1937.              * the baud rate however.
  1938.              */
  1939.  
  1940.         if(Status != -1)
  1941.         {
  1942.             WriteRequest->io_SerFlags = Status & 0xFF;
  1943.             WriteRequest->io_ExtFlags = 0;
  1944.  
  1945.             if(Status & ST_PARTYMARKON)
  1946.                 WriteRequest->io_ExtFlags |= SEXTF_MSPON;
  1947.  
  1948.             if(Status & ST_PARTYMARK)
  1949.                 WriteRequest->io_ExtFlags |= SEXTF_MARK;
  1950.  
  1951.             if(Status & ST_2BITS)
  1952.                 WriteRequest->io_StopBits = 2;
  1953.             else
  1954.                 WriteRequest->io_StopBits = 1;
  1955.  
  1956.             if(Status & ST_READ7)
  1957.                 WriteRequest->io_ReadLen = 7;
  1958.             else
  1959.                 WriteRequest->io_ReadLen = 8;
  1960.  
  1961.             if(Status & ST_WRITE7)
  1962.                 WriteRequest->io_WriteLen = 7;
  1963.             else
  1964.                 WriteRequest->io_WriteLen = 8;
  1965.  
  1966.             WriteRequest->IOSer.io_Command = SDCMD_SETPARAMS;
  1967.             DoIO(WriteRequest);
  1968.  
  1969.             CopyMem(WriteRequest,ReadRequest,sizeof(struct IOExtSer));
  1970.  
  1971.             ReadRequest->IOSer.io_Message.mn_ReplyPort = ReadPort;
  1972.  
  1973.             CopyWriteFlags();
  1974.  
  1975.             if(WriteRequest->io_SerFlags & SERF_7WIRE)
  1976.             {
  1977.                 if(Config->SerialConfig->HandshakingProtocol == HANDSHAKING_NONE)
  1978.                     Config->SerialConfig->HandshakingProtocol = HANDSHAKING_RTSCTS_DSR;
  1979.             }
  1980.             else
  1981.             {
  1982.                 if(Config->SerialConfig->HandshakingProtocol != HANDSHAKING_NONE)
  1983.                     Config->SerialConfig->HandshakingProtocol = HANDSHAKING_NONE;
  1984.             }
  1985.         }
  1986.  
  1987.         return(Return);
  1988.     }
  1989.     else
  1990.         return(-1);
  1991. }
  1992.  
  1993.     /* xpr_ffirst(STRPTR Buffer,STRPTR Pattern):
  1994.      *
  1995.      *    Batch file upload: find the first matching file and return
  1996.      *    its name.
  1997.      */
  1998.  
  1999. LONG __saveds __asm
  2000. xpr_ffirst(REG(a0) STRPTR Buffer,REG(a1) STRPTR Pattern)
  2001. {
  2002.     DB(kprintf("xpr_ffirst(0x%08lx,\"%s\")\n",Buffer,Pattern));
  2003.  
  2004.     if(FileTransferInfo)
  2005.     {
  2006.         FileTransferInfo->DoneSize    = 0;
  2007.         FileTransferInfo->DoneFiles    = 0;
  2008.  
  2009.         FileTransferInfo->CurrentFile    = (struct FileTransferNode *)FileTransferInfo->FileList.mlh_Head;
  2010.         FileTransferInfo->CurrentSize    = FileTransferInfo->CurrentFile->Size;
  2011.  
  2012.         if(Config->TransferConfig->MangleFileNames)
  2013.         {
  2014.             UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  2015.  
  2016.             strcpy(OriginalName,FileTransferInfo->CurrentFile->Name);
  2017.  
  2018.             ShrinkName(FilePart(FileTransferInfo->CurrentFile->Name),LocalName,12,TRUE);
  2019.  
  2020.             strcpy(Buffer,FileTransferInfo->CurrentFile->Name);
  2021.  
  2022.             Char = PathPart(Buffer);
  2023.  
  2024.             *Char = 0;
  2025.  
  2026.             AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  2027.  
  2028.             strcpy(ShrunkenName,Buffer);
  2029.         }
  2030.         else
  2031.         {
  2032.             OriginalName[0] = 0;
  2033.  
  2034.             strcpy(Buffer,FileTransferInfo->CurrentFile->Name);
  2035.         }
  2036.  
  2037.         return(1);
  2038.     }
  2039.     else
  2040.         return(0);
  2041. }
  2042.  
  2043.     /* xpr_fnext(LONG OldState,STRPTR Buffer,STRPTR Pattern):
  2044.      *
  2045.      *    Batch file upload: find the next matching file
  2046.      *    - if any - and return its name.
  2047.      */
  2048.  
  2049. LONG __saveds __asm
  2050. xpr_fnext(REG(d0) LONG OldState,REG(a0) STRPTR Buffer,REG(a1) STRPTR Pattern)
  2051. {
  2052.     DB(kprintf("xpr_fnext(%ld,0x%08lx,\"%s\")\n",OldState,Buffer,Pattern));
  2053.  
  2054.     if(FileTransferInfo)
  2055.     {
  2056.         if(FileTransferInfo->CurrentFile->Node.mln_Succ->mln_Succ)
  2057.         {
  2058.             FileTransferInfo->DoneSize    += FileTransferInfo->CurrentSize;
  2059.             FileTransferInfo->DoneFiles    += 1;
  2060.  
  2061.             FileTransferInfo->CurrentFile  = (struct FileTransferNode *)FileTransferInfo->CurrentFile->Node.mln_Succ;
  2062.             FileTransferInfo->CurrentSize  = FileTransferInfo->CurrentFile->Size;
  2063.  
  2064.             if(Config->TransferConfig->MangleFileNames)
  2065.             {
  2066.                 UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  2067.  
  2068.                 strcpy(OriginalName,FileTransferInfo->CurrentFile->Name);
  2069.  
  2070.                 ShrinkName(FilePart(FileTransferInfo->CurrentFile->Name),LocalName,12,TRUE);
  2071.  
  2072.                 strcpy(Buffer,FileTransferInfo->CurrentFile->Name);
  2073.  
  2074.                 Char = PathPart(Buffer);
  2075.  
  2076.                 *Char = 0;
  2077.  
  2078.                 AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  2079.  
  2080.                 strcpy(ShrunkenName,Buffer);
  2081.             }
  2082.             else
  2083.             {
  2084.                 OriginalName[0] = 0;
  2085.  
  2086.                 strcpy(Buffer,FileTransferInfo->CurrentFile->Name);
  2087.             }
  2088.  
  2089.             return(1);
  2090.         }
  2091.     }
  2092.  
  2093.     return(0);
  2094. }
  2095.  
  2096.     /* xpr_finfo(STRPTR FileName,LONG InfoType):
  2097.      *
  2098.      *    Return information on a given file.
  2099.      */
  2100.  
  2101. LONG __saveds __asm
  2102. xpr_finfo(REG(a0) STRPTR FileName,REG(d0) LONG InfoType)
  2103. {
  2104.     struct FileInfoBlock    *FileInfo;
  2105.     LONG             Size;
  2106.  
  2107.     DB(kprintf("xpr_finfo(\"%s\",%ld)\n",FileName,InfoType));
  2108.  
  2109.     switch(InfoType)
  2110.     {
  2111.             /* Return the file size. */
  2112.  
  2113.         case 1:
  2114.  
  2115.             Size = 0;
  2116.  
  2117.             if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2118.             {
  2119.                 UBYTE    RealName[MAX_FILENAME_LENGTH];
  2120.                 BPTR    FileLock;
  2121.  
  2122.                 if(OriginalName[0])
  2123.                 {
  2124.                     if(!Stricmp(ShrunkenName,FileName))
  2125.                         FileName = NewFileName(OriginalName,RealName);
  2126.                     else
  2127.                         FileName = NewFileName(FileName,RealName);
  2128.                 }
  2129.                 else
  2130.                     FileName = NewFileName(FileName,RealName);
  2131.  
  2132.                 if(FileLock = Lock(FileName,ACCESS_READ))
  2133.                 {
  2134.                     if(Examine(FileLock,FileInfo))
  2135.                     {
  2136.                         if(FileInfo->fib_DirEntryType < 0)
  2137.                             Size = FileInfo->fib_Size;
  2138.                     }
  2139.  
  2140.                     UnLock(FileLock);
  2141.                 }
  2142.  
  2143.                 FreeDosObject(DOS_FIB,FileInfo);
  2144.             }
  2145.  
  2146.             return(Size);
  2147.  
  2148.             /* Return the file transfer mode. */
  2149.  
  2150.         case 2:
  2151.  
  2152.             return(BinaryTransfer ? 1 : 2);
  2153.  
  2154.             /* Ignore the rest. */
  2155.  
  2156.         default:
  2157.  
  2158.             return(0);
  2159.     }
  2160. }
  2161.  
  2162.     /* xpr_options(LONG NumOpts,struct xpr_option **Opts):
  2163.      *
  2164.      *    Provide a more polished user interface to set the
  2165.      *    transfer protocol options.
  2166.      */
  2167.  
  2168. ULONG __saveds __asm
  2169. xpr_options(REG(d0) LONG NumOpts,REG(a0) struct xpr_option **Opts)
  2170. {
  2171.     DB(kprintf("xpr_options(%ld,0x%08lx)\n",NumOpts,Opts));
  2172.  
  2173.     if(NumOpts && Opts)
  2174.     {
  2175.         enum    {    GAD_USE=1,GAD_CANCEL,GAD_SPECIAL };
  2176.  
  2177.         LayoutHandle    *Handle;
  2178.         ULONG             Flags = NULL;
  2179.  
  2180.             /* We only have 32 bits! */
  2181.  
  2182.         if(NumOpts > 32)
  2183.             NumOpts = 32;
  2184.  
  2185.         if(Handle = LT_CreateHandleTags(Window->WScreen,
  2186.             LH_LocaleHook,    &LocaleHook,
  2187.         TAG_DONE))
  2188.         {
  2189.             struct Window    *PanelWindow;
  2190.             LONG             i,Split;
  2191.  
  2192.             if(NumOpts > 16)
  2193.                 Split = NumOpts / 2;
  2194.             else
  2195.                 Split = -1;
  2196.  
  2197.             LT_New(Handle,
  2198.                 LA_Type,VERTICAL_KIND,
  2199.             TAG_DONE);
  2200.             {
  2201.                 LT_New(Handle,
  2202.                     LA_Type,HORIZONTAL_KIND,
  2203.                 TAG_DONE);
  2204.                 {
  2205.                     LT_New(Handle,
  2206.                         LA_Type,VERTICAL_KIND,
  2207.                     TAG_DONE);
  2208.                     {
  2209.                         for(i = 0 ; i < NumOpts ; i++)
  2210.                         {
  2211.                             if(Opts[i])
  2212.                             {
  2213.                                 switch(Opts[i]->xpro_type)
  2214.                                 {
  2215.                                     case XPRO_BOOLEAN:
  2216.  
  2217.                                         LT_New(Handle,
  2218.                                             LA_Type,        CHECKBOX_KIND,
  2219.                                             LA_LabelText,    Opts[i]->xpro_description,
  2220.                                             LA_ID,            GAD_SPECIAL + i,
  2221.                                             GTCB_Checked,    String2Boolean(Opts[i]->xpro_value),
  2222.                                         TAG_DONE);
  2223.  
  2224.                                         break;
  2225.  
  2226.                                     case XPRO_LONG:
  2227.  
  2228.                                         LT_New(Handle,
  2229.                                             LA_Type,                INTEGER_KIND,
  2230.                                             LA_LabelText,            Opts[i]->xpro_description,
  2231.                                             LA_ID,                    GAD_SPECIAL + i,
  2232.                                             LA_Chars,                15,
  2233.                                             GTIN_Number,            Atol(Opts[i]->xpro_value),
  2234.                                             LAIN_UseIncrementers,    TRUE,
  2235.                                         TAG_DONE);
  2236.  
  2237.                                         break;
  2238.  
  2239.                                     case XPRO_STRING:
  2240.  
  2241.                                         LT_New(Handle,
  2242.                                             LA_Type,        STRING_KIND,
  2243.                                             LA_LabelText,    Opts[i]->xpro_description,
  2244.                                             LA_ID,            GAD_SPECIAL + i,
  2245.                                             LA_Chars,        15,
  2246.                                             GTST_String,    Opts[i]->xpro_value,
  2247.                                             GTST_MaxChars,    Opts[i]->xpro_length - 1,
  2248.                                         TAG_DONE);
  2249.  
  2250.                                         break;
  2251.  
  2252.                                     case XPRO_COMMPAR:
  2253.  
  2254.                                         LT_New(Handle,
  2255.                                             LA_Type,        STRING_KIND,
  2256.                                             LA_LabelText,    Opts[i]->xpro_description,
  2257.                                             LA_ID,            GAD_SPECIAL + i,
  2258.                                             LA_Chars,        15,
  2259.                                             LA_HighLabel,    TRUE,
  2260.                                             GTST_String,    Opts[i]->xpro_value,
  2261.                                             GTST_MaxChars,    Opts[i]->xpro_length - 1,
  2262.                                         TAG_DONE);
  2263.  
  2264.                                         break;
  2265.  
  2266.                                     case XPRO_HEADER:
  2267.  
  2268.                                         LT_New(Handle,
  2269.                                             LA_Type,        TEXT_KIND,
  2270.                                             LA_LabelText,    Opts[i]->xpro_description,
  2271.                                             LA_HighLabel,    TRUE,
  2272.                                             GTTX_Text,        " ",
  2273.                                         TAG_DONE);
  2274.  
  2275.                                         break;
  2276.  
  2277.                                     case XPRO_COMMAND:
  2278.  
  2279.                                         LT_New(Handle,
  2280.                                             LA_Type,        BUTTON_KIND,
  2281.                                             LA_LabelText,    Opts[i]->xpro_description,
  2282.                                             LA_ID,            GAD_SPECIAL + i,
  2283.                                             LA_Chars,        15,
  2284.                                         TAG_DONE);
  2285.  
  2286.                                         break;
  2287.                                 }
  2288.                             }
  2289.  
  2290.                             if(i == Split)
  2291.                             {
  2292.                                 LT_EndGroup(Handle);
  2293.  
  2294.                                 LT_New(Handle,
  2295.                                     LA_Type,VERTICAL_KIND,
  2296.                                 TAG_DONE);
  2297.                                 {
  2298.                                     LT_New(Handle,
  2299.                                         LA_Type,YBAR_KIND,
  2300.                                     TAG_DONE);
  2301.  
  2302.                                     LT_EndGroup(Handle);
  2303.                                 }
  2304.  
  2305.                                 LT_New(Handle,
  2306.                                     LA_Type,VERTICAL_KIND,
  2307.                                 TAG_DONE);
  2308.                             }
  2309.                         }
  2310.  
  2311.                         LT_EndGroup(Handle);
  2312.                     }
  2313.  
  2314.                     LT_EndGroup(Handle);
  2315.                 }
  2316.  
  2317.                 LT_New(Handle,
  2318.                     LA_Type,VERTICAL_KIND,
  2319.                 TAG_DONE);
  2320.                 {
  2321.                     LT_New(Handle,
  2322.                         LA_Type,        XBAR_KIND,
  2323.                         LAXB_FullSize,    TRUE,
  2324.                     TAG_DONE);
  2325.  
  2326.                     LT_EndGroup(Handle);
  2327.                 }
  2328.  
  2329.                 LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  2330.                     LAGR_SameSize,    TRUE,
  2331.                     LAGR_Spread,    TRUE,
  2332.                 TAG_DONE);
  2333.                 {
  2334.                     LT_New(Handle,
  2335.                         LA_Type,        BUTTON_KIND,
  2336.                         LA_LabelID,        MSG_GLOBAL_USE_GAD,
  2337.                         LA_ID,            GAD_USE,
  2338.                         LABT_ReturnKey,    TRUE,
  2339.                         LABT_ExtraFat,    TRUE,
  2340.                     TAG_DONE);
  2341.  
  2342.                     LT_New(Handle,
  2343.                         LA_Type,        BUTTON_KIND,
  2344.                         LA_LabelID,        MSG_GLOBAL_CANCEL_GAD,
  2345.                         LA_ID,            GAD_CANCEL,
  2346.                         LABT_EscKey,    TRUE,
  2347.                         LABT_ExtraFat,    TRUE,
  2348.                     TAG_DONE);
  2349.  
  2350.                     LT_EndGroup(Handle);
  2351.                 }
  2352.  
  2353.                 LT_EndGroup(Handle);
  2354.             }
  2355.  
  2356.             if(PanelWindow = LT_Layout(Handle,OptionTitle ? OptionTitle : LocaleString(MSG_TERMXPR_TRANSFER_OPTIONS_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  2357.                 LAWN_HelpHook,        &GuideHook,
  2358.                 LAWN_Parent,        Window,
  2359.                 WA_DepthGadget,        TRUE,
  2360.                 WA_CloseGadget,        TRUE,
  2361.                 WA_DragBar,            TRUE,
  2362.                 WA_RMBTrap,            TRUE,
  2363.                 WA_Activate,        TRUE,
  2364.             TAG_DONE))
  2365.             {
  2366.                 struct IntuiMessage    *Message;
  2367.                 BOOLEAN                 Done = FALSE;
  2368.                 ULONG                 MsgClass,
  2369.                                      MsgQualifier;
  2370.                 UWORD                 MsgCode;
  2371.                 struct Gadget        *MsgGadget;
  2372.                 BOOLEAN                 CheckFlags = FALSE;
  2373.  
  2374.                 PushWindow(PanelWindow);
  2375.  
  2376.                 LT_ShowWindow(Handle,TRUE);
  2377.  
  2378.                 do
  2379.                 {
  2380.                     if(Wait(PORTMASK(PanelWindow->UserPort) | SIG_BREAK) & SIG_BREAK)
  2381.                         break;
  2382.  
  2383.                     while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow->UserPort))
  2384.                     {
  2385.                         MsgClass        = Message->Class;
  2386.                         MsgQualifier    = Message->Qualifier;
  2387.                         MsgCode            = Message->Code;
  2388.                         MsgGadget        = (struct Gadget *)Message->IAddress;
  2389.  
  2390.                         GT_ReplyIMsg(Message);
  2391.  
  2392.                         LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  2393.  
  2394.                         if(MsgClass == IDCMP_CLOSEWINDOW)
  2395.                             Done = TRUE;
  2396.  
  2397.                         if(MsgClass == IDCMP_GADGETUP)
  2398.                         {
  2399.                             switch(MsgGadget->GadgetID)
  2400.                             {
  2401.                                 case GAD_USE:
  2402.  
  2403.                                     Done = CheckFlags = TRUE;
  2404.                                     break;
  2405.  
  2406.                                 case GAD_CANCEL:
  2407.  
  2408.                                     Done = TRUE;
  2409.                                     break;
  2410.  
  2411.                                 default:
  2412.  
  2413.                                     if(MsgGadget->GadgetID - GAD_SPECIAL < NumOpts)
  2414.                                     {
  2415.                                         i = MsgGadget->GadgetID - GAD_SPECIAL;
  2416.  
  2417.                                         if(Opts[i]->xpro_type == XPRO_COMMAND || (Opts[i]->xpro_type == XPRO_COMMPAR && MsgCode != '\t'))
  2418.                                         {
  2419.                                             Flags = (1L << i);
  2420.  
  2421.                                             XPRCommandSelected = Done = CheckFlags = TRUE;
  2422.                                         }
  2423.                                     }
  2424.  
  2425.                                     break;
  2426.                             }
  2427.                         }
  2428.                     }
  2429.                 }
  2430.                 while(!Done);
  2431.  
  2432.                 PopWindow();
  2433.  
  2434.                 if(CheckFlags)
  2435.                 {
  2436.                     LT_LockWindow(PanelWindow);
  2437.  
  2438.                     for(i = 0 ; i < NumOpts ; i++)
  2439.                     {
  2440.                         if(Opts[i])
  2441.                         {
  2442.                             switch(Opts[i]->xpro_type)
  2443.                             {
  2444.                                 case XPRO_BOOLEAN:
  2445.  
  2446.                                     if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE) != String2Boolean(Opts[i]->xpro_value))
  2447.                                     {
  2448.                                         Flags |= (1L << i);
  2449.  
  2450.                                         if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2451.                                             strcpy(Opts[i]->xpro_value,"yes");
  2452.                                         else
  2453.                                             strcpy(Opts[i]->xpro_value,"no");
  2454.  
  2455.                                         NewOptions = TRUE;
  2456.                                     }
  2457.  
  2458.                                     break;
  2459.  
  2460.                                 case XPRO_LONG:
  2461.  
  2462.                                     if(Atol(Opts[i]->xpro_value) != LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2463.                                     {
  2464.                                         Flags |= (1L << i);
  2465.  
  2466.                                         SPrintf(Opts[i]->xpro_value,"%ld",LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2467.  
  2468.                                         NewOptions = TRUE;
  2469.                                     }
  2470.  
  2471.                                     break;
  2472.  
  2473.                                 case XPRO_STRING:
  2474.  
  2475.                                     if(strcmp(Opts[i]->xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE)))
  2476.                                     {
  2477.                                         Flags |= (1L << i);
  2478.  
  2479.                                         strcpy(Opts[i]->xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2480.  
  2481.                                         NewOptions = TRUE;
  2482.                                     }
  2483.  
  2484.                                     break;
  2485.                             }
  2486.                         }
  2487.                     }
  2488.  
  2489.                     LT_UnlockWindow(PanelWindow);
  2490.                 }
  2491.                 else
  2492.                     Flags = NULL;
  2493.             }
  2494.  
  2495.             LT_DeleteHandle(Handle);
  2496.         }
  2497.  
  2498.         return(Flags);
  2499.     }
  2500.     else
  2501.         return(NULL);
  2502. }
  2503.  
  2504.     /* xpr_unlink(STRPTR FileName):
  2505.      *
  2506.      *    Remove (delete) a given file.
  2507.      */
  2508.  
  2509. LONG __saveds __asm
  2510. xpr_unlink(REG(a0) STRPTR FileName)
  2511. {
  2512.     DB(kprintf("xpr_unlink(\"%s\")\n",FileName));
  2513.  
  2514.         /* Sorry, but it is far too dangerous to let the protocol
  2515.          * remove any files with path name substitution enabled.
  2516.          * The protocol could accidentally hit the wrong file.
  2517.          */
  2518.  
  2519.     if(!Config->TransferConfig->OverridePath)
  2520.     {
  2521.         if(OriginalName[0])
  2522.         {
  2523.             if(!Stricmp(ShrunkenName,FileName))
  2524.                 FileName = OriginalName;
  2525.         }
  2526.  
  2527.         if(DeleteFile(FileName))
  2528.         {
  2529.             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_DELETE_FILE_TXT),FilePart(FileName));
  2530.  
  2531.             return(0);
  2532.         }
  2533.     }
  2534.  
  2535.     return(-1);
  2536. }
  2537.  
  2538.     /* xpr_squery():
  2539.      *
  2540.      *    Check how many characters are present in the serial buffer.
  2541.      */
  2542.  
  2543. LONG __saveds __asm
  2544. xpr_squery()
  2545. {
  2546.     DB(kprintf("xpr_squery()\n"));
  2547.  
  2548.     if(WriteRequest)
  2549.     {
  2550.         ULONG    Waiting;
  2551.         UWORD    Status;
  2552.  
  2553.         GetSerialInfo(&Waiting,&Status);
  2554.  
  2555.             /* Return error if carrier is lost. */
  2556.  
  2557.         if((Status & CIAF_COMCD) && Config->SerialConfig->CheckCarrier && !Config->SerialConfig->DirectConnection)
  2558.         {
  2559.             if(!CarrierMessage)
  2560.             {
  2561.                 CarrierMessage = TRUE;
  2562.  
  2563.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  2564.             }
  2565.  
  2566.             SetOnlineState(FALSE);
  2567.  
  2568.             TransferError = TRUE;
  2569.         }
  2570.         else
  2571.             return((LONG)Waiting);
  2572.     }
  2573.  
  2574.     return(-1);
  2575. }
  2576.  
  2577.     /* xpr_getptr(LONG InfoType):
  2578.      *
  2579.      *    Return a pointer to the term custom screen.
  2580.      */
  2581.  
  2582. LONG __saveds __asm
  2583. xpr_getptr(REG(d0) LONG InfoType)
  2584. {
  2585.     DB(kprintf("xpr_getptr(%ld)\n",InfoType));
  2586.  
  2587.     if(InfoType == 1)
  2588.         return((LONG)Window->WScreen);
  2589.     else
  2590.         return(-1);
  2591. }
  2592.  
  2593.     /* xpr_stealopts(STRPTR Prompt,STRPTR Buffer):
  2594.      *
  2595.      *    Steal the contents of the options buffer (replacement
  2596.      *    for xpr_gets).
  2597.      */
  2598.  
  2599. LONG __saveds __asm
  2600. xpr_stealopts(REG(a0) STRPTR Prompt,REG(a1) STRPTR Buffer)
  2601. {
  2602.     DB(kprintf("xpr_stealopts(\"%s\",\"%s\")\n",Prompt,Buffer));
  2603.  
  2604.     if(Buffer)
  2605.         strcpy(ProtocolOptsBuffer,Buffer);
  2606.  
  2607.     return(1);
  2608. }
  2609.